﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using NetworkingLibrary.Clients.Specialised;
using NetworkingLibrary.Servers.Specialised;
using NetworkingLibrary.Messages;
using NetworkingLibrary.Messages.Specialised.Game;
using NetworkingLibrary.Events;
using NetworkingLibrary.Exceptions;

using System.Net;
using System.Threading;

namespace GameServer_Test_Application
{
    class Program
    {
        static int ServerTCPPort = 56789;
        static int ServerUDPPort = 5000;
        
        static Random Rand = new Random();

        static int MaxConnections = 10;
        
        static IPAddress MulticastAddress = IPAddress.Parse("224.192.6.7");
        static IPAddress LocalMachineAddress = Dns.GetHostAddresses(Dns.GetHostName()).First();

        static ManualResetEvent TestMessagesReceivedEvent = new ManualResetEvent(false);
        static int NumTestMessagesReceived = 0;
        static int NumTestMessagesSent = 0;

        static void Main(string[] args)
        {
            try
            {
                GameServer TheServer = new GameServer(ServerTCPPort, ServerUDPPort, LocalMachineAddress.ToString(), MulticastAddress, MaxConnections);
                Console.WriteLine("Server started.");

                TheServer.OnClientConnect += TheServer_OnClientConnect;
                TheServer.OnClientDisconnect += TheServer_OnClientDisconnect;
                TheServer.OnError += TheServer_OnError;
                TheServer.OnMaxConnections += TheServer_OnMaxConnections;
                TheServer.OnMessageReceived += TheServer_OnMessageReceived;
                Console.WriteLine("Server events attached.");


                try
                {
                    GameServerClient Client1 = new GameServerClient(ServerTCPPort, ServerUDPPort, LocalMachineAddress, MulticastAddress, false);
                    Console.WriteLine("Client1 connected.");

                    try
                    {
                        GameServerClient Client2 = new GameServerClient(ServerTCPPort, ServerUDPPort, LocalMachineAddress, MulticastAddress, false);
                        Console.WriteLine("Client2 connected.");

                        Client1.Send(new byte[1]);
                        Client1.SendUDP(new byte[1]);
                        Client2.Send(new byte[1]);
                        Client2.SendUDP(new byte[1]);

                        Console.WriteLine("Pausing...");
                        Thread.Sleep(1000);

                        bool Terminate = false;
                        while (!Terminate)
                        {
                            Console.WriteLine();
                            Console.WriteLine();
                            Console.WriteLine("-----------------------------------------");
                            Console.WriteLine();
                            Console.WriteLine("Press enter to send test message or escape to exit.");
                            ConsoleKeyInfo Input = Console.ReadKey();

                            if (Input.Key == ConsoleKey.Enter)
                            {
                                TestMessage AMessage = new TestMessage(new Random().Next(), "Your TCP random number 1 is : ");
                                //Thread.Sleep(100) required otherwise the Random returns exact same number twice.
                                Thread.Sleep(200);
                                TestMessage BMessage = new TestMessage(new Random().Next(), "Your TCP random number 2 is : ");
                                Thread.Sleep(200);
                                TestMessage CMessage = new TestMessage(new Random().Next(), "Your UDP random number 1 is : ");
                                Thread.Sleep(200);
                                TestMessage DMessage = new TestMessage(new Random().Next(), "Your UDP random number 2 is : ");

                                TestMessagesReceivedEvent.Reset();
                                NumTestMessagesReceived = 0;
                                NumTestMessagesSent = 4;

                                Client1.Send(AMessage);
                                Client2.Send(BMessage);
                                Client1.SendUDP(CMessage);
                                Client2.SendUDP(DMessage);

                                TestMessagesReceivedEvent.WaitOne(10000);
                            }
                            else if (Input.Key == ConsoleKey.Escape)
                            {
                                Terminate = true;
                            }

                        }

                        Console.WriteLine("Pausing...");
                        Thread.Sleep(1000);

                        if (!Client2.Disconnect())
                        {
                            Console.WriteLine("Failed to disconnect Client2!");
                        }
                        else
                        {
                            Console.WriteLine("Client2 disconnected.");
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("Exception creating Client2 :\n" + ex.Message);
                        Console.WriteLine();
                    }

                    if (!Client1.Disconnect())
                    {
                        Console.WriteLine("Failed to disconnect Client1!");
                    }
                    else
                    {
                        Console.WriteLine("Client1 disconnected.");
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Exception creating Client1 :\n" + ex.Message);
                    Console.WriteLine();
                }

                Console.WriteLine("Pausing...");
                Thread.Sleep(1000);

                if (!TheServer.Stop())
                {
                    Console.WriteLine("Failed to stop game server!");
                }
                else
                {
                    Console.WriteLine("Server stoppped.");
                }
            }
            catch(Exception ex)
            {
                Console.WriteLine("Exception creating game server :\n" + ex.Message);
                Console.WriteLine();
            }
            Console.WriteLine("Press any key to exit...");
            Console.ReadLine();
        }

        static void TheServer_OnMessageReceived(MessageReceivedEventArgs e)
        {
            Console.WriteLine("Server: Message received. Type: " + e.TheMessage.GetType().Name);
            Type MessageType = e.TheMessage.GetType();
            if (MessageType == typeof(TestMessage))
            {
                TestMessage TheMessage = (TestMessage)e.TheMessage;
                Console.WriteLine(TheMessage.StringTest + TheMessage.NumberTest);
                NumTestMessagesReceived++;
                if (NumTestMessagesReceived == NumTestMessagesSent)
                {
                    TestMessagesReceivedEvent.Set();
                }
            }
        }
        static void TheServer_OnMaxConnections(MaxConnectionsEventArgs e)
        {
            Console.WriteLine("Server: Max connections reached.");
        }
        static void TheServer_OnError(ErrorEventArgs e)
        {
            Console.WriteLine("Server: Error! \n" + e.TheException.Message);
        }
        static void TheServer_OnClientDisconnect(ClientDisconnectEventArgs e)
        {
            Console.WriteLine("Server: Client disconnected.");
        }
        static void TheServer_OnClientConnect(ClientConnectEventArgs e)
        {
            Console.WriteLine("Server: Client connected.");
        }
    }
}




                    